﻿

using F29ServerProcess.Interfaces;
using F29ServerProcess.Models;
using IotContract.Dtos.Servers.Process;
using IotContract.Dtos.Servers.Pushs;
using IotContract.Enums;
using IotContract.Interfaces;
using IotContract.Interfaces.Process;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Extensions;
using XT.Common.Services;

namespace _29ServerProcess.DataProcess;
/// <summary>
/// 拘束机数据处理程序
/// </summary>
public class RestraintDataProcess : IServerProcessHandle
{

    private readonly IServerMainManager _mainProcess;
    private readonly IProcessDataService _processDataService;
    private readonly ILogService _logService;

    public RestraintDataProcess(IServerMainManager serverMainManager, IProcessDataService processDataService, ILogService logService)
    {
        _mainProcess = serverMainManager;
        _processDataService = processDataService;
        _logService = logService;
    }
    public string ProcessName { get; set; } =  F29ServerConst.ProcessName;
    public IotEquipType ProcessType { get; set; } = IotEquipType.RESTRAINT;


    private ConcurrentDictionary<string, F29CvUnitDto> _cvDic = new ConcurrentDictionary<string, F29CvUnitDto>();

    public async Task<bool> ParsingData()
    {
        try
        {
            // 获取数据
            var equips = await _mainProcess.GetEquips<PushSiemensS7Dto>(new IotContract.Models.Clients.ClientRequestCommand
            {
                RequestType = IotEquipType.RESTRAINT.ToString(),
                ProtobufType = IotProtobufType.SIEMENS_S7.ToString()
            });


            var resUnitDic = _processDataService.RestraintUnits;
            // 拘束机点位不需要设置UnitNum
            Parallel.ForEach(equips, equip =>
            {
                var tags = equip.Tags;
                F29RestraintUnitDto resUnit = null;
                if (resUnitDic.ContainsKey(equip.Num))
                {
                    resUnit = resUnitDic[equip.Num];
                }
                else
                {
                    resUnit = new F29RestraintUnitDto();
                    resUnit.EquipNum = equip.Num;
                    resUnit.UnitNum = equip.UnitNum;
                    resUnit.BindNum = equip.BindNum;
                    resUnit.EquipId = equip.Id;
                    resUnit.Connection = equip.Connection;
                    resUnitDic.TryAdd(equip.Num, resUnit);
                }
                SetUnitTag(resUnit, tags);

                if (equip.UnitNum.IsNotNullOrEmpty())
                {
                    var cv=  _processDataService.CvUnitTags.GetValueOrDefault(equip.UnitNum.To<int>());
                    if (cv != null)
                    {
                        if (_cvDic.ContainsKey(equip.Num))
                        {
                            _cvDic[equip.Num] = cv;
                        }
                        else
                        {
                            _cvDic.TryAdd(equip.Num, cv);
                        }
                    }
                }
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return true;
    }

    /// <summary>
    /// 取值
    /// </summary>
    /// <param name="scUnit"></param>
    /// <param name="tags"></param>
    private void SetUnitTag(F29RestraintUnitDto resUnit, List<PushEquipTag> tags)
    {
        resUnit.Tags = tags;
        Parallel.ForEach(resUnit.Tags, tag =>
        {
            int.TryParse(tag.Value, out int result);
            switch (tag.TagProperty)
            {
                case "ERROR":
                    {
                        resUnit.Error = result;
                        break;
                    }
                case "MODE":
                    {
                        resUnit.Mode = result;
                        break;
                    }
                case "WORK_DONE":
                    {
                        resUnit.WorkDone = result;
                        break;
                    }
                case "WORK_START":
                    {
                        resUnit.WorkStart = result;
                        break;
                    }
                case "TRAY":
                    {
                        resUnit.Tray = tag.Value;
                        break;
                    }
                case "TRAY_ARRIVE":
                    {
                        resUnit.TrayArrive = result;
                        break;
                    }


            }
        });
    }

    public async Task<bool> ProcessData()
    {
        foreach(var restraint in _processDataService.RestraintUnits.Values)
        {
           

            if (restraint.Tray.IsNullOrEmpty() || restraint.Tray.Replace("\0", "").IsNullOrEmpty() || restraint.Mode==0)
            {
                restraint.Status = 0;
                restraint.Message = string.Empty;
                continue;
            }
            // 托盘到达  要写入动作信息W_ACTION 1：作业     2：通过
            // 当作业开始前，写入W_WORK_START,确认开始作业
            // 作业结束后，写入W_WORK_DONE，确认作业完成
            if (restraint.Message.IsNotNullOrEmpty()) continue;
            if (restraint.TrayArrive == 1 && restraint.Status == 0 && restraint.WorkStart==0)
                {
                    // 验证数据
                    var result = await _processDataService.ValidateEnterTray(restraint.EquipNum,ProcessType,restraint.Tray);
                
                    if (result.Success)
                    {
                          await _processDataService.WriteRestraint("W_WORK_START", restraint.EquipNum);
                         
                       
                         restraint.Status = 1;
                        
                    }
                    else
                    {
                        // 有NG信息
                        restraint.Message = result.Message;
                        await Task.Delay(500);
                    }
                }
            else if(restraint.Status == 1 && restraint.WorkDone==1)
                {
                    var oResult = await _processDataService.ValidateOutTray(restraint.EquipNum, ProcessType, restraint.Tray);
                    if (oResult.Success)
                    {

                        await _processDataService.WriteRestraint("W_WORK_DONE", restraint.EquipNum);

                        restraint.Status = 2;
                    }
                    else
                    {
                        restraint.Message = oResult.Message;
                    await Task.Delay(500);
                    }
                }

            




        }
        return true;
    }

    public async Task<bool> ProcessOrder()
    {
        return true;
    }

    public async Task<bool> ProcessWarn()
    {
        return true;
    }

    public bool Stop()
    {
        _processDataService.ScUnits.Clear();
        return true;
    }
}
